local name, DB = ...

local make_filter_entry = function (capture, type)
	local value = loadstring("return " .. capture)()
	return ("%" .. type):format(value)
end

local default_add = function (self, identifier, amount)
	local current = self.totals[identifier]
	if not current then
		current = amount
		self.identifiers[#self.identifiers + 1] = identifier
		self.events[identifier] = 1
	else
		current = current + amount
		self.events[identifier] = self.events[identifier] + 1
	end
	if self.max < current then
		self.max = current
	end
	self.total = self.total + amount
	self.totals[identifier] = current
	self:Update()
end

local clear = function (self)
	self.identifiers = {}
	self.totals = {}
	self.events = {}
	self.max = 0
	self.total = 0
	self.Add = default_add
end

local clear_on_next_add = function (self, ...)
	clear(self)
	self.last_update = nil
	return default_add(self, ...)
end

DB.DataSet = DB.Class{
	constructor = function (self, ...)
		self:Clear()
		self._sorting_handler = function (a, b)
			local va, vb = self.totals[a], self.totals[b]
			if va == vb then
				return a < b
			else
				return va > vb
			end
		end
		local i = 1
		while true do
			local events, filter = select(i, ...)
			if not events then break end
			if type(filter) == "string" then
				filter = loadstring(filter:gsub("%$(%b())([dfqs])", make_filter_entry))()
			end
			DB.recorder:AddHandler(events, function(...)
				local id, value = filter(...)
				if id then self:Add(id, value) end
			end)
			i = i + 2
		end
	end,
	Clear = function (self)
		clear(self)
		self:Update(true)
	end,
	Add = default_add,
	ClearOnNextAdd = function (self)
		self.Add = clear_on_next_add
	end,
	Save = function (self, db)
		db.totals = self.totals
		db.events = self.events
	end,
	Load = function (self, db)
		self.totals = db.totals or self.totals
		self.events = db.events or self.events
		self.identifiers = {}
		local total, max = 0, 0
		for id, value in next, self.totals do
			table.insert(self.identifiers, id)
			total = total + value
			if value > max then
				max = value
			end
		end
		self.total = total
		self.max = max
		self:Update(true)
	end,
	GetValues = function(self, id)
		return self:GetName(id), self.events[id], self.totals[id], self.max, self.total
	end,
	GetName = function (self, id)
		return id
	end,
	Update = function (self, force)
		local window = self.window
		local current_time
		if not window then return end
		if not self.last_update then
			force = true
		else
			current_time = GetTime()
			if  (current_time - self.last_update) > DB.SV.UpdateFrequency then
				force = true
			end
		end
		if not force then return end
		self.last_update = current_time or GetTime()
		window:Reset()
		table.sort(self.identifiers, self._sorting_handler)
		for _, id in ipairs(self.identifiers) do
			local line = window:NextLine()
			if not line then break end
			line:Set(self:GetValues(id))
		end
		window:Finalize()
	end
}
